package com.innovation.wjrpc.rpc;

import com.innovation.wjrpc.codec.Decoder;
import com.innovation.wjrpc.codec.Encoder;
import com.innovation.wjrpc.loader.TransportSelector;
import com.innovation.wjrpc.util.ReflectionUtils;

import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Proxy;

/**
 * @author innoyiya
 * @date 2021/9/7 19:46
 */
public class RpcClient {
    private RpcClientConfig config;

    private Encoder encoder;

    private Decoder decoder;

    private TransportSelector selector;

    public RpcClient() {
        this(new RpcClientConfig());
    }

    public RpcClient(RpcClientConfig config) {
        this.config = config;
        this.encoder = ReflectionUtils.newInstance(this.config.getEncoderClass());
        this.decoder = ReflectionUtils.newInstance(this.config.getDecoderClass());
        this.selector = ReflectionUtils.newInstance(this.config.getSelectorClass());

        this.selector.init(this.config.getServers(), this.config.getConnectCount(), this.config.getTransportClass());
    }

    public <T> T getProxy(Class<T> clazz, Class<? extends RemoteInvoker> invokerClass)  {

        return (T) Proxy.newProxyInstance(
                getClass().getClassLoader(),
                new Class[]{clazz},
                //new RemoteInvoker(clazz, encoder, decoder, selector)
                ReflectionUtils.newInstance(invokerClass,clazz, encoder, decoder, selector)
        );
//        return (T) Proxy.newProxyInstance(
//                getClass().getClassLoader(),
//                new Class[]{clazz},
//                //new RemoteInvoker(clazz, encoder, decoder, selector)
//                (proxy, method, args) -> {
//                    Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class
//                            .getDeclaredConstructor(Class.class);
//                    constructor.setAccessible(true);
//                    constructor.newInstance(clazz)
//                            .in(clazz)
//                            .unreflectSpecial(method, clazz)
//                            .bindTo(proxy);
//                    return ReflectionUtils.newInstance(invokerClass,clazz, encoder, decoder, selector);
//                }
//        );
    }
}

